package com.sunmnet.j2ee.service.powerdb.designer.impl;

import com.sunmnet.j2ee.bean.powerdb.designer.chart.BeChart;
import com.sunmnet.j2ee.bean.powerdb.designer.cus.CusEntity;
import com.sunmnet.j2ee.bean.powerdb.designer.cus.CusPDM;
import com.sunmnet.j2ee.core.powerdb.designer.Commons;
import com.sunmnet.j2ee.core.pub.sqlloader.SqlLoader;
import com.sunmnet.j2ee.dao.BaseDruidDao;
import com.sunmnet.j2ee.entity.powerdb.designer.*;
import com.sunmnet.j2ee.service.powerdb.designer.*;
import com.sunmnet.j2ee.utils.BeanUtil;
import com.sunmnet.j2ee.utils.JsonUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <PRE>
 * 绘图数据转换
 * </PRE>
 * <B>项    目：</B>J2EE开发平台
 * <B>技术支持：</B>三盟科技 (c) 2016
 *
 * @author 黄坚：huangjian@sunmnet.com
 * @version 1.0 2016/8/8
 * @since jdk版本：jdk1.7
 */
@Repository("/powerdb/designer/pdmService")
public class PDMServiceImpl implements PDMService {

	/**
	 * json格式数据存储时，对于双引号的转义符号
	 **/
	public static final String SYNBOL = "#";

	@Resource(name = "pdmDao")
	private BaseDruidDao dao;

	private final static String CLASS_NAME = PDMServiceImpl.class.getName();

	private final static String UPDATE_ENTITY_RELATE_POINTS = SqlLoader.getInstance()
			.getSql(CLASS_NAME, "UPDATE_ENTITY_RELATE_POINTS");

	private final static String UPDATE_ENTITY_POINTS = SqlLoader.getInstance()
			.getSql(CLASS_NAME, "UPDATE_ENTITY_POINTS");

	/**
	 * log4j2日志
	 **/
	private static final Logger LOG = LogManager.getLogger(PDMServiceImpl.class.getName());

	@Resource(name = "/powerdb/designer/moduleService")
	private ModuleService moduleService;

	@Resource(name = "/powerdb/designer/entityService")
	private EntityService entityService;

	@Resource(name = "/powerdb/designer/fieldService")
	private FieldService fieldService;

	@Resource(name = "/powerdb/designer/indexInfoService")
	private IndexInfoService indexInfoService;

	@Resource(name = "/powerdb/designer/entityRelateService")
	private EntityRelateService entityRelatService;

	@Resource(name = "/powerdb/designer/projectService")
	private ProjectService projectService;

	@Resource(name = "/powerdb/designer/databaseService")
	private DatabaseService databaseService;

	@Override
	public CusPDM getPDM(Long moduleId, Long versionId) {
		if (versionId == null) {
			versionId = Commons.DEF_VERSION_ID;
		}
		PdmModule module = null;
		List<Entity> entitys = null;
		List<IndexInfo> indexs = null;
		List<Field> fields = null;
		EntityRelate rel = null;
		long id = 0;
		Project project = null;
		Database db = null;
		CusEntity cusEntity = null;
		List<EntityRelate> entityRelates = null;

		CusPDM pdm = new CusPDM();

		module = moduleService.get(moduleId, versionId);
		LOG.debug("module: {}", module);
		pdm.setId(module.getId());
		pdm.setName(module.getName());
		project = projectService.get(module.getProjectId());
		LOG.debug("project: {}", project);
		pdm.setProject(project);
		if (module.getDatabaseId() != null) {
			//FIXME 模块创建时，是否需要把数据库id作为必填
			db = databaseService.get(module.getDatabaseId(), versionId);
		}
		pdm.setDbInfo(db);
		LOG.debug("db: {}", db);
		List<CusEntity> cusEntitys = new ArrayList<>();
		entitys = entityService.getEntitys(moduleId, versionId);
		LOG.debug("entitys: {}", entitys);
		entityRelates = entityRelatService.getEntityRelates(moduleId, versionId);
		LOG.debug("EntityRelate: {}", entityRelates);
		pdm.setRelates(entityRelates);

		for (Entity entity : entitys) {
			id = entity.getId();
			fields = fieldService.getFields(id, versionId);
			LOG.debug("fields: {}", fields);
			indexs = indexInfoService.getIndexs(id, versionId);
			LOG.debug("indexs: {}", indexs);
			cusEntity = createCusEntity(entity, fields, indexs);
			cusEntitys.add(cusEntity);
		}
		pdm.setEntitys(cusEntitys);

		return pdm;
	}

	/**
	 * 创建自定义的实体关系队列
	 *
	 * @param rels 数据库存储的实体关系队列
	 * @return 自定义的实体关系队列
	 */
/*	protected List<CusEntityRelate> creeateCusRelate(List<EntityRelate> rels) {
		List<CusEntityRelate> cusRels = new ArrayList<>();
		CusEntityRelate cusRel = null;
		for (EntityRelate rel : rels) {
			cusRel = new CusEntityRelate();
			BeanUtil.copyProperties(rel, cusRel);
			cusRels.add(cusRel);
		}
		return cusRels;
	}*/

	/**
	 * 创建自定义实体对象
	 *
	 * @param entity 数据库存储实体对象
	 * @param fields 数据库存储字段对象队列
	 * @param indexs 数据库存储索引对象队列
	 * @return 自定义实体对象
	 */
	protected CusEntity createCusEntity(Entity entity, List<Field> fields, List<IndexInfo> indexs) {
		CusEntity cusEntity = new CusEntity();
		BeanUtil.copyProperties(entity, cusEntity);
		cusEntity.setFields(fields);
		cusEntity.setIndexs(indexs);
		return cusEntity;
	}

	@Override
	public BeChart getChart(Long moduleId, Long versionId) {
		return pdmToChart(
				getPDM(moduleId, versionId));
	}

	/**
	 * 获取前端呈现的绘图数据
	 *
	 * @param moduleId 模块编号
	 * @return 前端格式的绘图对象
	 */
	@Override
	public BeChart getChart(Long moduleId) {
		return getChart(moduleId, -1L);
	}

	/**
	 * 获取前端使用的绘图对象
	 * @param pdm 自定义的PDM对象
	 * @return  前端绘图对象
	 */
	protected BeChart pdmToChart(CusPDM pdm) {
		BeChart chart = new BeChart();
		chart.setId(pdm.getId() + "");
		chart.setName(pdm.getName());
		chart.setProject(pdm.getProject());
		chart.setLineInfo(pdm.getRelates());
		chart.setDomainShapeInfo(pdm.getEntitys());
		return chart;
	}

	@Override
	public void updateChart(String jsonEntitys, String jsonRelates) {
		List<Entity> listEntitys = JsonUtils.fromJsonArray(jsonEntitys, Entity.class);
		LOG.debug("jsonEntitys to list: {}", listEntitys);
		updateEntitys(listEntitys);
		List<EntityRelate> listRelates = JsonUtils.fromJsonArray(jsonRelates, EntityRelate.class);
		updateEntityRelates(listRelates);
		LOG.debug("listRelates to list: {}", listEntitys);
	}

	/**
	 * 更新实体关系坐标数据
	 * @param listRelates 实体关系对象队列
	 */
	protected void updateEntityRelates(List<EntityRelate> listRelates) {
		for (EntityRelate relate : listRelates) {
			updateEntityRelate(relate);
		}
	}

	/**
	 * 更新实体关系坐标数据
	 * @param relate 实体关系对象
	 */
	protected void updateEntityRelate(EntityRelate relate) {
		int re = dao.executeSql(UPDATE_ENTITY_RELATE_POINTS,
				new Object[]{relate.getPoints(),
						relate.getMultiplicityJson()
								.replace("\"", SYNBOL)
								.replace("&quot;", SYNBOL),
						relate.getId(),
						Commons.DEF_VERSION_ID});
		LOG.debug("updateEntityRelate: {}, result: {}", relate, re);
	}

	/**
	 * 更新实体对象的坐标数据
	 * @param listEntitys 实体对象队列
	 */
	protected void updateEntitys(List<Entity> listEntitys) {
		for (Entity entity : listEntitys) {
			updateEntity(entity);
		}
	}

	/**
	 * 更新实体对象的坐标数据
	 * @param entity 实体对象
	 */
	protected void updateEntity(Entity entity) {
		int re = dao.executeSql(UPDATE_ENTITY_POINTS,
				new Object[]{entity.getxPosition(),
						entity.getyPosition(),
						entity.getId(),
						Commons.DEF_VERSION_ID});
		LOG.debug("updateEntity: {}, result: {}", entity, re);
	}


	/**
	 * 版本数据创建
	 *
	 * @param moduleId  模块编号
	 * @param versionId 版本编号
	 */

	@Override
	public void copyDatas(Long moduleId, Long versionId) throws Exception {

		/*
			1.通过版本id和模块id拷贝新版本的模块，获取到新版本模块的id
			2.首先拷贝表。将所有拷贝表的id和对应原表id放到一个表id关系对应map中
			3.接着拷贝字段，将所有拷贝字段的id和对应原字段id放到一个字段id关系对应map中，
			  拷贝字段中的表id可在表id关系对应map中获取。
			4.接着拷贝索引，索引中的表id和字段id都可在map中获取到对应的新id
			5.最后拷贝关系，关系中的表id和字段id都可在map中获取到对应的新id
		 */

		Map<Long, Long> copyedEntitys;
		Map<Long, Long> copyedFields;

		//拷贝新模块
		PdmModule module = moduleService.get(moduleId);
		module = moduleService.copyModules(module, versionId);
		Long newModuleId = module.getId();

		//拷贝新数据库
		Database database = databaseService.get(module.getDatabaseId());
		databaseService.copyDatabases(database, versionId);

		//拷贝新表
		List<Entity> listEntity = entityService.getEntitys(moduleId, Commons.DEF_VERSION_ID);
		copyedEntitys = entityService.copyEntitys(listEntity, versionId, newModuleId);

		//拷贝新字段
		List<Field> fieldList = fieldService.getFieldsByModuleId(moduleId, Commons.DEF_VERSION_ID);
		copyedFields = fieldService.copyFields(fieldList, copyedEntitys, versionId, newModuleId);

		//拷贝新索引
		List<IndexInfo> listIndexInfo = indexInfoService.getIndexInfos(moduleId, Commons.DEF_VERSION_ID);
		indexInfoService.copyIndexs(listIndexInfo, copyedEntitys, copyedFields, versionId, newModuleId);

		//拷贝新关系
		List<EntityRelate> listEntityRelate = entityRelatService.getEntityRelates(moduleId, Commons.DEF_VERSION_ID);
		entityRelatService.copyEntityRelates(listEntityRelate, copyedEntitys, copyedFields, versionId, newModuleId);
	}
}
